package com.fluxtah.jordl.generator.strategy;

import com.fluxtah.jordl.generator.CodeGenerationContext;
import com.fluxtah.jordl.generator.ModelExtensions;
import com.fluxtah.jordl.generator.strategy.MemberSerializationStatementGenerator;
import com.fluxtah.jordl.model.ArrayType;
import com.fluxtah.jordl.model.BlockType;
import com.fluxtah.jordl.model.BodyBlock;
import com.fluxtah.jordl.model.Client;
import com.fluxtah.jordl.model.ComplexTypeDeclaration;
import com.fluxtah.jordl.model.ComplexTypeLiteral;
import com.fluxtah.jordl.model.EnumTypeDeclaration;
import com.fluxtah.jordl.model.GenericListType;
import com.fluxtah.jordl.model.HttpDelete;
import com.fluxtah.jordl.model.HttpGet;
import com.fluxtah.jordl.model.HttpMethod;
import com.fluxtah.jordl.model.HttpPost;
import com.fluxtah.jordl.model.HttpPut;
import com.fluxtah.jordl.model.IntrinsicType;
import com.fluxtah.jordl.model.JordlModule;
import com.fluxtah.jordl.model.Member;
import com.fluxtah.jordl.model.MergeMember;
import com.fluxtah.jordl.model.ParamsBlock;
import com.fluxtah.jordl.model.SimpleMember;
import com.fluxtah.jordl.model.Type;
import com.fluxtah.jordl.model.TypedMember;
import com.fluxtah.jordl.model.UserType;
import com.fluxtah.jordl.model.UserTypeDeclaration;
import java.util.Arrays;
import org.eclipse.emf.common.util.EList;
import org.eclipse.xtend2.lib.StringConcatenation;
import org.eclipse.xtext.xbase.lib.BooleanExtensions;
import org.eclipse.xtext.xbase.lib.Conversions;
import org.eclipse.xtext.xbase.lib.Functions.Function1;
import org.eclipse.xtext.xbase.lib.IntegerExtensions;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import org.eclipse.xtext.xbase.lib.ObjectExtensions;
import org.eclipse.xtext.xbase.lib.StringExtensions;

@SuppressWarnings("all")
public class RequestGenerator {
  private CodeGenerationContext context;
  
  public CodeGenerationContext setContext(final CodeGenerationContext context) {
    CodeGenerationContext _context = this.context = context;
    return _context;
  }
  
  private MemberSerializationStatementGenerator serializationStatementGenerator;
  
  public MemberSerializationStatementGenerator setMemberSerializationStatementGenerator(final MemberSerializationStatementGenerator serializationStatementGenerator) {
    MemberSerializationStatementGenerator _serializationStatementGenerator = this.serializationStatementGenerator = serializationStatementGenerator;
    return _serializationStatementGenerator;
  }
  
  public MemberSerializationStatementGenerator getMemberSerializationStatementGenerator() {
    return this.serializationStatementGenerator;
  }
  
  public CharSequence registerImports() {
    StringConcatenation _builder = new StringConcatenation();
    return _builder;
  }
  
  public CharSequence generate(final HttpMethod method, final JordlModule module, final Client client) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("package ");
    String _packageName = module.getPackageName();
    _builder.append(_packageName, "");
    _builder.append(";");
    _builder.newLineIfNotEmpty();
    _builder.newLine();
    CharSequence _generateRequestClass = this.generateRequestClass(method, module, client);
    CharSequence body = _generateRequestClass;
    _builder.newLineIfNotEmpty();
    CharSequence _registerImports = this.registerImports();
    _builder.append(_registerImports, "");
    _builder.newLineIfNotEmpty();
    _builder.append("import com.fluxtah.jordl.lib.TransformerProvider;");
    _builder.newLine();
    _builder.append("import com.fluxtah.jordl.lib.TransformException;");
    _builder.newLine();
    _builder.append("import com.fluxtah.jordl.lib.HttpRequestHelper;");
    _builder.newLine();
    _builder.append("import com.fluxtah.jordl.lib.WebResponse;");
    _builder.newLine();
    _builder.append("import java.io.IOException;");
    _builder.newLine();
    _builder.append("import org.apache.http.client.ClientProtocolException;");
    _builder.newLine();
    CodeGenerationContext _context = this.context;
    org.eclipse.xtext.xtend2.lib.StringConcatenation _printImports = _context.printImports();
    _builder.append(_printImports, "");
    _builder.newLineIfNotEmpty();
    CodeGenerationContext _context_1 = this.context;
    _context_1.clearImports();
    _builder.newLineIfNotEmpty();
    _builder.newLine();
    _builder.append(body, "");
    _builder.newLineIfNotEmpty();
    return _builder;
  }
  
  public CharSequence generateRequestClass(final HttpMethod method, final JordlModule module, final Client client) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("public class ");
    String _name = method.getName();
    String _pascalize = ModelExtensions.pascalize(_name);
    _builder.append(_pascalize, "");
    _builder.append("Request {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("private static final String PATH=\"");
    String _pathAsFormatString = ModelExtensions.getPathAsFormatString(method);
    _builder.append(_pathAsFormatString, "	");
    _builder.append("\";");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    Iterable<String> _argsFromPath = ModelExtensions.getArgsFromPath(method);
    Iterable<String> pathArgs = _argsFromPath;
    _builder.newLineIfNotEmpty();
    {
      int _size = IterableExtensions.size(pathArgs);
      boolean _operator_greaterThan = IntegerExtensions.operator_greaterThan(_size, 0);
      if (_operator_greaterThan) {
        {
          for(final String segment : pathArgs) {
            _builder.append("\t");
            _builder.append("private final String ");
            String _substring = segment.substring(1);
            String _camelize = ModelExtensions.camelize(_substring);
            String _escapeReserved = ModelExtensions.escapeReserved(_camelize);
            _builder.append(_escapeReserved, "	");
            _builder.append(";");
            _builder.newLineIfNotEmpty();
          }
        }
      }
    }
    {
      ParamsBlock _params = method.getParams();
      boolean _operator_notEquals = ObjectExtensions.operator_notEquals(_params, null);
      if (_operator_notEquals) {
        _builder.append("\t");
        CodeGenerationContext _context = this.context;
        _context.registerImport("android.net.Uri");
        _builder.newLineIfNotEmpty();
        {
          ParamsBlock _params_1 = method.getParams();
          EList<SimpleMember> _params_2 = _params_1.getParams();
          for(final SimpleMember param : _params_2) {
            _builder.append("\t");
            _builder.append("private ");
            IntrinsicType _type = param.getType();
            String _signature = ModelExtensions.signature(_type);
            _builder.append(_signature, "	");
            _builder.append(" ");
            String _name_1 = param.getName();
            String _camelize_1 = ModelExtensions.camelize(_name_1);
            _builder.append(_camelize_1, "	");
            _builder.append("Param;");
            _builder.newLineIfNotEmpty();
          }
        }
        _builder.append("\t");
        _builder.newLine();
      }
    }
    {
      boolean _hasBody = ModelExtensions.hasBody(method);
      if (_hasBody) {
        {
          BodyBlock _body = ModelExtensions.getBody(method);
          BlockType _type_1 = _body.getType();
          if ((_type_1 instanceof ComplexTypeLiteral)) {
            _builder.append("\t");
            BodyBlock _body_1 = ModelExtensions.getBody(method);
            BlockType _type_2 = _body_1.getType();
            ComplexTypeLiteral body = ((ComplexTypeLiteral) _type_2);
            _builder.newLineIfNotEmpty();
            {
              EList<Member> _members = body.getMembers();
              for(final Member member : _members) {
                _builder.append("\t");
                CharSequence _generateField = this.generateField(member);
                _builder.append(_generateField, "	");
                _builder.newLineIfNotEmpty();
              }
            }
          } else {
            BodyBlock _body_2 = ModelExtensions.getBody(method);
            BlockType _type_3 = _body_2.getType();
            if ((_type_3 instanceof IntrinsicType)) {
              _builder.append("\t");
              BodyBlock _body_3 = ModelExtensions.getBody(method);
              BlockType _type_4 = _body_3.getType();
              IntrinsicType simpleType = ((IntrinsicType) _type_4);
              _builder.newLineIfNotEmpty();
              _builder.append("\t");
              _builder.append("private final ");
              String _signature_1 = ModelExtensions.signature(simpleType);
              _builder.append(_signature_1, "	");
              _builder.append(" value;");
              _builder.newLineIfNotEmpty();
            } else {
              BodyBlock _body_4 = ModelExtensions.getBody(method);
              BlockType _type_5 = _body_4.getType();
              if ((_type_5 instanceof ArrayType)) {
                _builder.append("\t");
                BodyBlock _body_5 = ModelExtensions.getBody(method);
                BlockType _type_6 = _body_5.getType();
                ArrayType arrayType = ((ArrayType) _type_6);
                _builder.newLineIfNotEmpty();
                {
                  Type _elementType = arrayType.getElementType();
                  if ((_elementType instanceof IntrinsicType)) {
                    _builder.append("\t");
                    _builder.append("private final ");
                    String _signature_2 = ModelExtensions.signature(arrayType);
                    _builder.append(_signature_2, "	");
                    _builder.append(" values;");
                    _builder.newLineIfNotEmpty();
                  } else {
                    _builder.append("\t");
                    _builder.append("private final ");
                    String _signature_3 = ModelExtensions.signature(arrayType);
                    _builder.append(_signature_3, "	");
                    _builder.append(" ");
                    String _innerSignature = ModelExtensions.innerSignature(arrayType);
                    String _camelize_2 = ModelExtensions.camelize(_innerSignature);
                    String _pluralize = ModelExtensions.pluralize(_camelize_2);
                    _builder.append(_pluralize, "	");
                    _builder.append(";");
                    _builder.newLineIfNotEmpty();
                  }
                }
              } else {
                BodyBlock _body_6 = ModelExtensions.getBody(method);
                BlockType _type_7 = _body_6.getType();
                if ((_type_7 instanceof GenericListType)) {
                  _builder.append("\t");
                  BodyBlock _body_7 = ModelExtensions.getBody(method);
                  BlockType _type_8 = _body_7.getType();
                  GenericListType listType = ((GenericListType) _type_8);
                  _builder.newLineIfNotEmpty();
                  {
                    Type _genericType = listType.getGenericType();
                    if ((_genericType instanceof IntrinsicType)) {
                      _builder.append("\t");
                      _builder.append("private final ");
                      String _signature_4 = ModelExtensions.signature(listType);
                      _builder.append(_signature_4, "	");
                      _builder.append(" values;");
                      _builder.newLineIfNotEmpty();
                    } else {
                      _builder.append("\t");
                      _builder.append("private final ");
                      String _signature_5 = ModelExtensions.signature(listType);
                      _builder.append(_signature_5, "	");
                      _builder.append(" ");
                      String _innerSignature_1 = ModelExtensions.innerSignature(listType);
                      String _camelize_3 = ModelExtensions.camelize(_innerSignature_1);
                      String _pluralize_1 = ModelExtensions.pluralize(_camelize_3);
                      _builder.append(_pluralize_1, "	");
                      _builder.append(";");
                      _builder.newLineIfNotEmpty();
                    }
                  }
                } else {
                  BodyBlock _body_8 = ModelExtensions.getBody(method);
                  BlockType _type_9 = _body_8.getType();
                  if ((_type_9 instanceof UserType)) {
                    _builder.append("\t");
                    BodyBlock _body_9 = ModelExtensions.getBody(method);
                    BlockType _type_10 = _body_9.getType();
                    UserType type = ((UserType) _type_10);
                    _builder.newLineIfNotEmpty();
                    _builder.append("\t");
                    _builder.append("private final ");
                    String _signature_6 = ModelExtensions.signature(type);
                    _builder.append(_signature_6, "	");
                    _builder.append(" ");
                    String _signature_7 = ModelExtensions.signature(type);
                    String _camelize_4 = ModelExtensions.camelize(_signature_7);
                    _builder.append(_camelize_4, "	");
                    _builder.append(";");
                    _builder.newLineIfNotEmpty();
                  }
                }
              }
            }
          }
        }
        _builder.append("\t");
        _builder.newLine();
      }
    }
    {
      ParamsBlock _params_3 = method.getParams();
      boolean _operator_notEquals_1 = ObjectExtensions.operator_notEquals(_params_3, null);
      if (_operator_notEquals_1) {
        {
          ParamsBlock _params_4 = method.getParams();
          EList<SimpleMember> _params_5 = _params_4.getParams();
          for(final SimpleMember param_1 : _params_5) {
            _builder.append("\t");
            _builder.append("public void set");
            String _name_2 = param_1.getName();
            String _pascalize_1 = ModelExtensions.pascalize(_name_2);
            _builder.append(_pascalize_1, "	");
            _builder.append("Param(");
            IntrinsicType _type_11 = param_1.getType();
            String _signature_8 = ModelExtensions.signature(_type_11);
            _builder.append(_signature_8, "	");
            _builder.append(" value) {");
            _builder.newLineIfNotEmpty();
            _builder.append("\t");
            _builder.append("\t");
            _builder.append("this.");
            String _name_3 = param_1.getName();
            String _camelize_5 = ModelExtensions.camelize(_name_3);
            _builder.append(_camelize_5, "		");
            _builder.append("Param = value;");
            _builder.newLineIfNotEmpty();
            _builder.append("\t");
            _builder.append("}");
            _builder.newLine();
          }
        }
        _builder.append("\t");
        _builder.newLine();
      }
    }
    _builder.append("\t");
    _builder.append("public ");
    String _name_4 = method.getName();
    String _pascalize_2 = ModelExtensions.pascalize(_name_4);
    _builder.append(_pascalize_2, "	");
    _builder.append("Request(");
    String _path = method.getPath();
    BodyBlock _body_10 = ModelExtensions.getBody(method);
    String _generateRequestConstructorArgs = this.generateRequestConstructorArgs(_path, _body_10);
    _builder.append(_generateRequestConstructorArgs, "	");
    _builder.append("){");
    _builder.newLineIfNotEmpty();
    {
      int _size_1 = IterableExtensions.size(pathArgs);
      boolean _operator_greaterThan_1 = IntegerExtensions.operator_greaterThan(_size_1, 0);
      if (_operator_greaterThan_1) {
        {
          for(final String segment_1 : pathArgs) {
            _builder.append("\t\t");
            _builder.append("this.");
            String _substring_1 = segment_1.substring(1);
            String _camelize_6 = ModelExtensions.camelize(_substring_1);
            String _escapeReserved_1 = ModelExtensions.escapeReserved(_camelize_6);
            _builder.append(_escapeReserved_1, "		");
            _builder.append(" = ");
            String _substring_2 = segment_1.substring(1);
            String _camelize_7 = ModelExtensions.camelize(_substring_2);
            String _escapeReserved_2 = ModelExtensions.escapeReserved(_camelize_7);
            _builder.append(_escapeReserved_2, "		");
            _builder.append(";");
            _builder.newLineIfNotEmpty();
          }
        }
      }
    }
    {
      boolean _hasBody_1 = ModelExtensions.hasBody(method);
      if (_hasBody_1) {
        {
          BodyBlock _body_11 = ModelExtensions.getBody(method);
          BlockType _type_12 = _body_11.getType();
          if ((_type_12 instanceof ComplexTypeLiteral)) {
            _builder.append("\t\t");
            BodyBlock _body_12 = ModelExtensions.getBody(method);
            BlockType _type_13 = _body_12.getType();
            ComplexTypeLiteral body_1 = ((ComplexTypeLiteral) _type_13);
            _builder.newLineIfNotEmpty();
            {
              EList<Member> _members_1 = body_1.getMembers();
              for(final Member member_1 : _members_1) {
                _builder.append("\t\t");
                _builder.append("this.");
                String _identifier = ModelExtensions.toIdentifier(member_1);
                _builder.append(_identifier, "		");
                _builder.append(" = ");
                String _identifier_1 = ModelExtensions.toIdentifier(member_1);
                _builder.append(_identifier_1, "		");
                _builder.append(";");
                _builder.newLineIfNotEmpty();
              }
            }
          } else {
            BodyBlock _body_13 = ModelExtensions.getBody(method);
            BlockType _type_14 = _body_13.getType();
            if ((_type_14 instanceof IntrinsicType)) {
              _builder.append("\t\t");
              _builder.append("this.value = value;");
              _builder.newLine();
            } else {
              BodyBlock _body_14 = ModelExtensions.getBody(method);
              BlockType _type_15 = _body_14.getType();
              if ((_type_15 instanceof ArrayType)) {
                _builder.append("\t\t");
                BodyBlock _body_15 = ModelExtensions.getBody(method);
                BlockType _type_16 = _body_15.getType();
                ArrayType arrayType_1 = ((ArrayType) _type_16);
                _builder.newLineIfNotEmpty();
                {
                  Type _elementType_1 = arrayType_1.getElementType();
                  if ((_elementType_1 instanceof IntrinsicType)) {
                    _builder.append("\t\t");
                    _builder.append("this.values = values;");
                    _builder.newLine();
                  } else {
                    _builder.append("\t\t");
                    _builder.append("this.");
                    String _innerSignature_2 = ModelExtensions.innerSignature(arrayType_1);
                    String _camelize_8 = ModelExtensions.camelize(_innerSignature_2);
                    String _pluralize_2 = ModelExtensions.pluralize(_camelize_8);
                    _builder.append(_pluralize_2, "		");
                    _builder.append(" = ");
                    String _innerSignature_3 = ModelExtensions.innerSignature(arrayType_1);
                    String _camelize_9 = ModelExtensions.camelize(_innerSignature_3);
                    String _pluralize_3 = ModelExtensions.pluralize(_camelize_9);
                    _builder.append(_pluralize_3, "		");
                    _builder.append(";");
                    _builder.newLineIfNotEmpty();
                  }
                }
              } else {
                BodyBlock _body_16 = ModelExtensions.getBody(method);
                BlockType _type_17 = _body_16.getType();
                if ((_type_17 instanceof GenericListType)) {
                  _builder.append("\t\t");
                  BodyBlock _body_17 = ModelExtensions.getBody(method);
                  BlockType _type_18 = _body_17.getType();
                  GenericListType listType_1 = ((GenericListType) _type_18);
                  _builder.newLineIfNotEmpty();
                  {
                    Type _genericType_1 = listType_1.getGenericType();
                    if ((_genericType_1 instanceof IntrinsicType)) {
                      _builder.append("\t\t");
                      _builder.append("this.values = values;");
                      _builder.newLine();
                    } else {
                      _builder.append("\t\t");
                      _builder.append("this.");
                      String _innerSignature_4 = ModelExtensions.innerSignature(listType_1);
                      String _camelize_10 = ModelExtensions.camelize(_innerSignature_4);
                      String _pluralize_4 = ModelExtensions.pluralize(_camelize_10);
                      _builder.append(_pluralize_4, "		");
                      _builder.append(" = ");
                      String _innerSignature_5 = ModelExtensions.innerSignature(listType_1);
                      String _camelize_11 = ModelExtensions.camelize(_innerSignature_5);
                      String _pluralize_5 = ModelExtensions.pluralize(_camelize_11);
                      _builder.append(_pluralize_5, "		");
                      _builder.append(";");
                      _builder.newLineIfNotEmpty();
                    }
                  }
                } else {
                  BodyBlock _body_18 = ModelExtensions.getBody(method);
                  BlockType _type_19 = _body_18.getType();
                  if ((_type_19 instanceof UserType)) {
                    _builder.append("\t\t");
                    BodyBlock _body_19 = ModelExtensions.getBody(method);
                    BlockType _type_20 = _body_19.getType();
                    UserType type_1 = ((UserType) _type_20);
                    _builder.newLineIfNotEmpty();
                    _builder.append("\t\t");
                    _builder.append("this.");
                    String _signature_9 = ModelExtensions.signature(type_1);
                    String _camelize_12 = ModelExtensions.camelize(_signature_9);
                    _builder.append(_camelize_12, "		");
                    _builder.append(" = ");
                    String _signature_10 = ModelExtensions.signature(type_1);
                    String _camelize_13 = ModelExtensions.camelize(_signature_10);
                    _builder.append(_camelize_13, "		");
                    _builder.append(";");
                    _builder.newLineIfNotEmpty();
                  }
                }
              }
            }
          }
        }
        _builder.append("\t\t");
        _builder.newLine();
      }
    }
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("\t");
    _builder.newLine();
    {
      boolean _hasBody_2 = ModelExtensions.hasBody(method);
      if (_hasBody_2) {
        _builder.append("\t");
        _builder.append("public String createBody(TransformerProvider transformerProvider) throws TransformException {");
        _builder.newLine();
        _builder.append("\t");
        _builder.append("\t");
        BodyBlock _body_20 = ModelExtensions.getBody(method);
        BodyBlock _body_21 = ModelExtensions.getBody(method);
        BlockType _type_21 = _body_21.getType();
        CharSequence _generateSerializationStatementForType = this.generateSerializationStatementForType(_body_20, _type_21);
        _builder.append(_generateSerializationStatementForType, "		");
        _builder.newLineIfNotEmpty();
        _builder.append("\t");
        _builder.append("}");
        _builder.newLine();
        _builder.append("\t");
        _builder.newLine();
      }
    }
    _builder.append("\t");
    _builder.append("public String createUrl(String baseUrl){");
    _builder.newLine();
    {
      ParamsBlock _params_6 = method.getParams();
      boolean _operator_notEquals_2 = ObjectExtensions.operator_notEquals(_params_6, null);
      if (_operator_notEquals_2) {
        {
          String _path_1 = method.getPath();
          boolean _hasArgs = this.hasArgs(_path_1);
          if (_hasArgs) {
            _builder.append("\t\t");
            _builder.append("Uri.Builder uriBuilder = Uri.parse(String.format(baseUrl + PATH");
            String _path_2 = method.getPath();
            String _pathToStringFormatArgs = this.pathToStringFormatArgs(_path_2);
            _builder.append(_pathToStringFormatArgs, "		");
            _builder.append(")).buildUpon();");
            _builder.newLineIfNotEmpty();
          } else {
            _builder.append("\t\t");
            _builder.append("Uri.Builder uriBuilder = Uri.parse(baseUrl + PATH).buildUpon();");
            _builder.newLine();
          }
        }
        {
          ParamsBlock _params_7 = method.getParams();
          EList<SimpleMember> _params_8 = _params_7.getParams();
          for(final SimpleMember param_2 : _params_8) {
            _builder.append("\t\t");
            _builder.append("if(");
            String _name_5 = param_2.getName();
            String _camelize_14 = ModelExtensions.camelize(_name_5);
            _builder.append(_camelize_14, "		");
            _builder.append("Param != null){");
            _builder.newLineIfNotEmpty();
            _builder.append("\t\t");
            _builder.append("\t");
            _builder.append("uriBuilder.appendQueryParameter(\"");
            String _name_6 = param_2.getName();
            _builder.append(_name_6, "			");
            _builder.append("\", ");
            String _name_7 = param_2.getName();
            String _camelize_15 = ModelExtensions.camelize(_name_7);
            _builder.append(_camelize_15, "			");
            _builder.append("Param.toString());");
            _builder.newLineIfNotEmpty();
            _builder.append("\t\t");
            _builder.append("}");
            _builder.newLine();
          }
        }
        _builder.newLine();
        _builder.append("\t\t");
        _builder.append("return uriBuilder.toString();");
        _builder.newLine();
      } else {
        {
          String _path_3 = method.getPath();
          boolean _hasArgs_1 = this.hasArgs(_path_3);
          if (_hasArgs_1) {
            _builder.append("\t\t");
            _builder.append("return String.format(baseUrl + PATH");
            String _path_4 = method.getPath();
            String _pathToStringFormatArgs_1 = this.pathToStringFormatArgs(_path_4);
            _builder.append(_pathToStringFormatArgs_1, "		");
            _builder.append(");");
            _builder.newLineIfNotEmpty();
          } else {
            _builder.append("\t\t");
            _builder.append("return baseUrl + PATH;");
            _builder.newLine();
          }
        }
      }
    }
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("protected ");
    String _name_8 = method.getName();
    String _pascalize_3 = ModelExtensions.pascalize(_name_8);
    _builder.append(_pascalize_3, "	");
    _builder.append("Response createResponse(String baseUrl, HttpRequestHelper requestHelper, TransformerProvider transformerProvider)");
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t");
    _builder.append("throws ClientProtocolException, IOException, TransformException {");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("String url = createUrl(baseUrl);");
    _builder.newLine();
    {
      if ((method instanceof HttpPut)) {
        _builder.append("\t\t");
        _builder.append("String body = createBody(transformerProvider);");
        _builder.newLine();
        _builder.append("\t\t");
        _builder.append("WebResponse response = requestHelper.putJson(url, body);");
        _builder.newLine();
      } else {
        if ((method instanceof HttpPost)) {
          _builder.append("\t\t");
          _builder.append("String body = createBody(transformerProvider);");
          _builder.newLine();
          _builder.append("\t\t");
          _builder.append("WebResponse response = requestHelper.postJson(url, body);");
          _builder.newLine();
        } else {
          if ((method instanceof HttpGet)) {
            _builder.append("\t\t");
            _builder.append("WebResponse response = requestHelper.getJson(url);");
            _builder.newLine();
          } else {
            if ((method instanceof HttpDelete)) {
              _builder.append("\t\t");
              _builder.append("WebResponse response = requestHelper.deleteJson(url);");
              _builder.newLine();
            }
          }
        }
      }
    }
    _builder.append("\t\t");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("return new ");
    String _name_9 = method.getName();
    String _pascalize_4 = ModelExtensions.pascalize(_name_9);
    _builder.append(_pascalize_4, "		");
    _builder.append("Response(transformerProvider, response);");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("}\t");
    _builder.newLine();
    return _builder;
  }
  
  protected CharSequence _generateField(final TypedMember member) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("private final ");
    Type _type = member.getType();
    String _signature = ModelExtensions.signature(_type);
    _builder.append(_signature, "");
    _builder.append(" ");
    String _identifier = ModelExtensions.toIdentifier(member);
    _builder.append(_identifier, "");
    _builder.append(";");
    _builder.newLineIfNotEmpty();
    return _builder;
  }
  
  protected CharSequence _generateField(final MergeMember member) {
    StringConcatenation _builder = new StringConcatenation();
    return _builder;
  }
  
  protected CharSequence _generateSerializationStatementForType(final BodyBlock body, final IntrinsicType type) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("return value.toString();");
    _builder.newLine();
    return _builder;
  }
  
  protected CharSequence _generateSerializationStatementForType(final BodyBlock body, final ComplexTypeLiteral type) {
    StringConcatenation _builder = new StringConcatenation();
    CodeGenerationContext _context = this.context;
    _context.registerImport("org.json.JSONObject");
    _builder.newLineIfNotEmpty();
    _builder.append("JSONObject target = new JSONObject();");
    _builder.newLine();
    {
      EList<Member> _members = type.getMembers();
      for(final Member member : _members) {
        MemberSerializationStatementGenerator _serializationStatementGenerator = this.serializationStatementGenerator;
        CharSequence _generate = _serializationStatementGenerator.generate(member, "transformerProvider", "this", "target", true);
        _builder.append(_generate, "");
        _builder.newLineIfNotEmpty();
      }
    }
    _builder.append("return target.toString();");
    _builder.newLine();
    return _builder;
  }
  
  protected CharSequence _generateSerializationStatementForType(final BodyBlock body, final UserType type) {
    UserTypeDeclaration _declaration = type.getDeclaration();
    CharSequence _generateSerializationStatementForUserType = this.generateSerializationStatementForUserType(body, type, _declaration);
    return _generateSerializationStatementForUserType;
  }
  
  protected CharSequence _generateSerializationStatementForUserType(final BodyBlock body, final UserType type, final ComplexTypeDeclaration declaration) {
    StringConcatenation _builder = new StringConcatenation();
    CodeGenerationContext _context = this.context;
    _context.registerImport("org.json.JSONObject");
    _builder.newLineIfNotEmpty();
    _builder.append("JSONObject target = new JSONObject();");
    _builder.newLine();
    _builder.append("transformerProvider.get(");
    String _signature = ModelExtensions.signature(type);
    _builder.append(_signature, "");
    _builder.append("OutputTransformer.class).transform(");
    String _signature_1 = ModelExtensions.signature(type);
    String _camelize = ModelExtensions.camelize(_signature_1);
    _builder.append(_camelize, "");
    _builder.append(", target);");
    _builder.newLineIfNotEmpty();
    _builder.append("return target.toString();");
    _builder.newLine();
    return _builder;
  }
  
  protected CharSequence _generateSerializationStatementForUserType(final BodyBlock body, final UserType type, final EnumTypeDeclaration declaration) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("return ");
    String _signature = ModelExtensions.signature(type);
    String _camelize = ModelExtensions.camelize(_signature);
    _builder.append(_camelize, "");
    _builder.append(".getValue();");
    _builder.newLineIfNotEmpty();
    return _builder;
  }
  
  protected CharSequence _generateSerializationStatementForType(final BodyBlock body, final ArrayType type) {
    Type _elementType = type.getElementType();
    CharSequence _generateSerializationStatementForArrayType = this.generateSerializationStatementForArrayType(body, type, _elementType);
    return _generateSerializationStatementForArrayType;
  }
  
  protected CharSequence _generateSerializationStatementForArrayType(final BodyBlock body, final ArrayType type, final IntrinsicType elementType) {
    StringConcatenation _builder = new StringConcatenation();
    CodeGenerationContext _context = this.context;
    _context.registerImport("org.json.JSONArray");
    _builder.newLineIfNotEmpty();
    _builder.append("JSONArray target = new JSONArray();");
    _builder.newLine();
    _builder.append("for(");
    String _innerSignature = ModelExtensions.innerSignature(type);
    _builder.append(_innerSignature, "");
    _builder.append(" element:values) {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("target.put(element);");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    _builder.append("return target.toString();");
    _builder.newLine();
    return _builder;
  }
  
  protected CharSequence _generateSerializationStatementForArrayType(final BodyBlock body, final ArrayType type, final UserType elementType) {
    UserTypeDeclaration _declaration = elementType.getDeclaration();
    CharSequence _generateSerializationStatementForUserTypeArray = this.generateSerializationStatementForUserTypeArray(body, type, elementType, _declaration);
    return _generateSerializationStatementForUserTypeArray;
  }
  
  protected CharSequence _generateSerializationStatementForUserTypeArray(final BodyBlock body, final ArrayType type, final UserType elementType, final ComplexTypeDeclaration declaration) {
    StringConcatenation _builder = new StringConcatenation();
    CodeGenerationContext _context = this.context;
    _context.registerImport("org.json.JSONArray");
    _builder.newLineIfNotEmpty();
    _builder.append("JSONArray target = new JSONArray();");
    _builder.newLine();
    _builder.append("transformerProvider.get(");
    String _innerSignature = ModelExtensions.innerSignature(type);
    _builder.append(_innerSignature, "");
    _builder.append("ArrayOutputTransformer.class).transform(");
    String _innerSignature_1 = ModelExtensions.innerSignature(type);
    String _camelize = ModelExtensions.camelize(_innerSignature_1);
    String _pluralize = ModelExtensions.pluralize(_camelize);
    _builder.append(_pluralize, "");
    _builder.append(", target);");
    _builder.newLineIfNotEmpty();
    _builder.append("return target.toString();");
    _builder.newLine();
    return _builder;
  }
  
  protected CharSequence _generateSerializationStatementForUserTypeArray(final BodyBlock body, final ArrayType type, final UserType elementType, final EnumTypeDeclaration declaration) {
    StringConcatenation _builder = new StringConcatenation();
    CodeGenerationContext _context = this.context;
    _context.registerImport("org.json.JSONArray");
    _builder.newLineIfNotEmpty();
    _builder.append("JSONArray target = new JSONArray();");
    _builder.newLine();
    _builder.append("for(");
    String _innerSignature = ModelExtensions.innerSignature(type);
    _builder.append(_innerSignature, "");
    _builder.append(" element:");
    String _innerSignature_1 = ModelExtensions.innerSignature(type);
    String _camelize = ModelExtensions.camelize(_innerSignature_1);
    String _pluralize = ModelExtensions.pluralize(_camelize);
    _builder.append(_pluralize, "");
    _builder.append(") {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("target.put(element.getValue());");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    _builder.append("return target.toString();");
    _builder.newLine();
    return _builder;
  }
  
  protected CharSequence _generateSerializationStatementForType(final BodyBlock body, final GenericListType type) {
    Type _genericType = type.getGenericType();
    CharSequence _generateSerializationStatementForGenericListType = this.generateSerializationStatementForGenericListType(body, type, _genericType);
    return _generateSerializationStatementForGenericListType;
  }
  
  protected CharSequence _generateSerializationStatementForGenericListType(final BodyBlock body, final GenericListType type, final IntrinsicType elementType) {
    StringConcatenation _builder = new StringConcatenation();
    CodeGenerationContext _context = this.context;
    _context.registerImport("org.json.JSONArray");
    _builder.newLineIfNotEmpty();
    CodeGenerationContext _context_1 = this.context;
    _context_1.registerImport("java.util.List");
    _builder.newLineIfNotEmpty();
    _builder.append("JSONArray target = new JSONArray(values);");
    _builder.newLine();
    _builder.append("return target.toString();");
    _builder.newLine();
    return _builder;
  }
  
  protected CharSequence _generateSerializationStatementForGenericListType(final BodyBlock body, final GenericListType type, final UserType elementType) {
    UserTypeDeclaration _declaration = elementType.getDeclaration();
    CharSequence _generateSerializationStatementForUserTypeGenericList = this.generateSerializationStatementForUserTypeGenericList(body, type, elementType, _declaration);
    return _generateSerializationStatementForUserTypeGenericList;
  }
  
  protected CharSequence _generateSerializationStatementForUserTypeGenericList(final BodyBlock body, final GenericListType type, final UserType elementType, final ComplexTypeDeclaration declaration) {
    StringConcatenation _builder = new StringConcatenation();
    CodeGenerationContext _context = this.context;
    _context.registerImport("org.json.JSONArray");
    _builder.newLineIfNotEmpty();
    CodeGenerationContext _context_1 = this.context;
    _context_1.registerImport("java.util.List");
    _builder.newLineIfNotEmpty();
    _builder.append("JSONArray target = new JSONArray();");
    _builder.newLine();
    _builder.append("transformerProvider.get(");
    String _innerSignature = ModelExtensions.innerSignature(type);
    _builder.append(_innerSignature, "");
    _builder.append("ListOutputTransformer.class).transform(");
    String _innerSignature_1 = ModelExtensions.innerSignature(type);
    String _camelize = ModelExtensions.camelize(_innerSignature_1);
    String _pluralize = ModelExtensions.pluralize(_camelize);
    _builder.append(_pluralize, "");
    _builder.append(", target);");
    _builder.newLineIfNotEmpty();
    _builder.append("return target.toString();");
    _builder.newLine();
    return _builder;
  }
  
  protected CharSequence _generateSerializationStatementForUserTypeGenericList(final BodyBlock body, final GenericListType type, final UserType elementType, final EnumTypeDeclaration declaration) {
    StringConcatenation _builder = new StringConcatenation();
    CodeGenerationContext _context = this.context;
    _context.registerImport("org.json.JSONArray");
    _builder.newLineIfNotEmpty();
    CodeGenerationContext _context_1 = this.context;
    _context_1.registerImport("java.util.List");
    _builder.newLineIfNotEmpty();
    _builder.append("JSONArray target = new JSONArray();");
    _builder.newLine();
    _builder.append("for(");
    String _innerSignature = ModelExtensions.innerSignature(type);
    _builder.append(_innerSignature, "");
    _builder.append(" element:");
    String _innerSignature_1 = ModelExtensions.innerSignature(type);
    String _camelize = ModelExtensions.camelize(_innerSignature_1);
    String _pluralize = ModelExtensions.pluralize(_camelize);
    _builder.append(_pluralize, "");
    _builder.append(") {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("target.put(element.getValue());");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    _builder.append("return target.toString();");
    _builder.newLine();
    return _builder;
  }
  
  /**
   * Converts a path (eg:- /qux/:fooparam/:quxparam/bar
   * into constructor arguments
   */
  public String generateRequestConstructorArgs(final String path, final BodyBlock body) {
      Iterable<String> _argsFromPath = ModelExtensions.getArgsFromPath(path);
      final Function1<String,String> _function = new Function1<String,String>() {
          public String apply(final String arg) {
            String _substring = arg.substring(1);
            String _camelize = ModelExtensions.camelize(_substring);
            String _escapeReserved = ModelExtensions.escapeReserved(_camelize);
            String _operator_plus = StringExtensions.operator_plus("String ", _escapeReserved);
            return _operator_plus;
          }
        };
      String _join = IterableExtensions.<String>join(_argsFromPath, ", ", _function);
      String args = _join;
      boolean _operator_notEquals = ObjectExtensions.operator_notEquals(body, null);
      if (_operator_notEquals) {
        {
          String _trim = args.trim();
          int _length = _trim.length();
          boolean _operator_greaterThan = IntegerExtensions.operator_greaterThan(_length, 0);
          if (_operator_greaterThan) {
            String _operator_plus = StringExtensions.operator_plus(args, ", ");
            args = _operator_plus;
          }
          BlockType _type = body.getType();
          if ((_type instanceof ComplexTypeLiteral)) {
            {
              BlockType _type_1 = body.getType();
              ComplexTypeLiteral bodyType = ((ComplexTypeLiteral) _type_1);
              EList<Member> _members = bodyType.getMembers();
              final Function1<Member,Boolean> _function_1 = new Function1<Member,Boolean>() {
                  public Boolean apply(final Member m) {
                    return Boolean.valueOf((m instanceof TypedMember));
                  }
                };
              Iterable<Member> _filter = IterableExtensions.<Member>filter(_members, _function_1);
              final Function1<Member,String> _function_2 = new Function1<Member,String>() {
                  public String apply(final Member m) {
                    Type _type = ((TypedMember) m).getType();
                    String _signature = ModelExtensions.signature(_type);
                    String _operator_plus = StringExtensions.operator_plus(_signature, " ");
                    String _identifier = ModelExtensions.toIdentifier(m);
                    String _operator_plus_1 = StringExtensions.operator_plus(_operator_plus, _identifier);
                    return _operator_plus_1;
                  }
                };
              String _join_1 = IterableExtensions.<Member>join(_filter, ", ", _function_2);
              String _operator_plus_1 = StringExtensions.operator_plus(args, _join_1);
              args = _operator_plus_1;
            }
          } else {
            BlockType _type_2 = body.getType();
            if ((_type_2 instanceof IntrinsicType)) {
              {
                BlockType _type_3 = body.getType();
                IntrinsicType simple = ((IntrinsicType) _type_3);
                String _signature = ModelExtensions.signature(simple);
                String _operator_plus_2 = StringExtensions.operator_plus(args, _signature);
                String _operator_plus_3 = StringExtensions.operator_plus(_operator_plus_2, " value");
                args = _operator_plus_3;
              }
            } else {
              BlockType _type_4 = body.getType();
              if ((_type_4 instanceof ArrayType)) {
                {
                  BlockType _type_5 = body.getType();
                  ArrayType arrayType = ((ArrayType) _type_5);
                  Type _elementType = arrayType.getElementType();
                  if ((_elementType instanceof IntrinsicType)) {
                    String _signature_1 = ModelExtensions.signature(arrayType);
                    String _operator_plus_4 = StringExtensions.operator_plus(args, _signature_1);
                    String _operator_plus_5 = StringExtensions.operator_plus(_operator_plus_4, " values");
                    args = _operator_plus_5;
                  } else {
                    String _signature_2 = ModelExtensions.signature(arrayType);
                    String _operator_plus_6 = StringExtensions.operator_plus(args, _signature_2);
                    String _operator_plus_7 = StringExtensions.operator_plus(_operator_plus_6, " ");
                    String _innerSignature = ModelExtensions.innerSignature(arrayType);
                    String _camelize = ModelExtensions.camelize(_innerSignature);
                    String _pluralize = ModelExtensions.pluralize(_camelize);
                    String _operator_plus_8 = StringExtensions.operator_plus(_operator_plus_7, _pluralize);
                    args = _operator_plus_8;
                  }
                }
              } else {
                BlockType _type_6 = body.getType();
                if ((_type_6 instanceof GenericListType)) {
                  {
                    BlockType _type_7 = body.getType();
                    GenericListType listType = ((GenericListType) _type_7);
                    Type _genericType = listType.getGenericType();
                    if ((_genericType instanceof IntrinsicType)) {
                      String _signature_3 = ModelExtensions.signature(listType);
                      String _operator_plus_9 = StringExtensions.operator_plus(args, _signature_3);
                      String _operator_plus_10 = StringExtensions.operator_plus(_operator_plus_9, " values");
                      args = _operator_plus_10;
                    } else {
                      String _signature_4 = ModelExtensions.signature(listType);
                      String _operator_plus_11 = StringExtensions.operator_plus(args, _signature_4);
                      String _operator_plus_12 = StringExtensions.operator_plus(_operator_plus_11, " ");
                      String _innerSignature_1 = ModelExtensions.innerSignature(listType);
                      String _camelize_1 = ModelExtensions.camelize(_innerSignature_1);
                      String _pluralize_1 = ModelExtensions.pluralize(_camelize_1);
                      String _operator_plus_13 = StringExtensions.operator_plus(_operator_plus_12, _pluralize_1);
                      args = _operator_plus_13;
                    }
                  }
                } else {
                  {
                    BlockType _type_8 = body.getType();
                    Type bodyType_1 = ((Type) _type_8);
                    String _signature_5 = ModelExtensions.signature(bodyType_1);
                    String _operator_plus_14 = StringExtensions.operator_plus(args, _signature_5);
                    String _operator_plus_15 = StringExtensions.operator_plus(_operator_plus_14, " ");
                    String _signature_6 = ModelExtensions.signature(bodyType_1);
                    String _camelize_2 = ModelExtensions.camelize(_signature_6);
                    String _operator_plus_16 = StringExtensions.operator_plus(_operator_plus_15, _camelize_2);
                    args = _operator_plus_16;
                  }
                }
              }
            }
          }
        }
      }
      return args;
  }
  
  public String pathToStringFormatArgs(final String path) {
    String[] _split = path.split("/");
    final Function1<String,Boolean> _function = new Function1<String,Boolean>() {
        public Boolean apply(final String seg) {
          boolean _startsWith = seg.startsWith(":");
          return Boolean.valueOf(_startsWith);
        }
      };
    Iterable<String> _filter = IterableExtensions.<String>filter(((Iterable<String>)Conversions.doWrapArray(_split)), _function);
    final Function1<String,String> _function_1 = new Function1<String,String>() {
        public String apply(final String arg) {
          String _substring = arg.substring(1);
          String _camelize = ModelExtensions.camelize(_substring);
          String _escapeReserved = ModelExtensions.escapeReserved(_camelize);
          return _escapeReserved;
        }
      };
    String _join = IterableExtensions.<String>join(_filter, ", ", _function_1);
    String _operator_plus = StringExtensions.operator_plus(", ", _join);
    return _operator_plus;
  }
  
  public boolean hasArgs(final String path) {
    boolean _operator_and = false;
    boolean _operator_notEquals = ObjectExtensions.operator_notEquals(path, null);
    if (!_operator_notEquals) {
      _operator_and = false;
    } else {
      boolean _contains = path.contains(":");
      _operator_and = BooleanExtensions.operator_and(_operator_notEquals, _contains);
    }
    return _operator_and;
  }
  
  public CharSequence generateField(final Member member) {
    if (member instanceof MergeMember) {
      return _generateField((MergeMember)member);
    } else if (member instanceof TypedMember) {
      return _generateField((TypedMember)member);
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.<Object>asList(member).toString());
    }
  }
  
  public CharSequence generateSerializationStatementForType(final BodyBlock body, final BlockType type) {
    if (type instanceof ArrayType) {
      return _generateSerializationStatementForType(body, (ArrayType)type);
    } else if (type instanceof GenericListType) {
      return _generateSerializationStatementForType(body, (GenericListType)type);
    } else if (type instanceof IntrinsicType) {
      return _generateSerializationStatementForType(body, (IntrinsicType)type);
    } else if (type instanceof UserType) {
      return _generateSerializationStatementForType(body, (UserType)type);
    } else if (type instanceof ComplexTypeLiteral) {
      return _generateSerializationStatementForType(body, (ComplexTypeLiteral)type);
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.<Object>asList(body, type).toString());
    }
  }
  
  public CharSequence generateSerializationStatementForUserType(final BodyBlock body, final UserType type, final UserTypeDeclaration declaration) {
    if (declaration instanceof ComplexTypeDeclaration) {
      return _generateSerializationStatementForUserType(body, type, (ComplexTypeDeclaration)declaration);
    } else if (declaration instanceof EnumTypeDeclaration) {
      return _generateSerializationStatementForUserType(body, type, (EnumTypeDeclaration)declaration);
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.<Object>asList(body, type, declaration).toString());
    }
  }
  
  public CharSequence generateSerializationStatementForArrayType(final BodyBlock body, final ArrayType type, final Type elementType) {
    if (elementType instanceof IntrinsicType) {
      return _generateSerializationStatementForArrayType(body, type, (IntrinsicType)elementType);
    } else if (elementType instanceof UserType) {
      return _generateSerializationStatementForArrayType(body, type, (UserType)elementType);
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.<Object>asList(body, type, elementType).toString());
    }
  }
  
  public CharSequence generateSerializationStatementForUserTypeArray(final BodyBlock body, final ArrayType type, final UserType elementType, final UserTypeDeclaration declaration) {
    if (declaration instanceof ComplexTypeDeclaration) {
      return _generateSerializationStatementForUserTypeArray(body, type, elementType, (ComplexTypeDeclaration)declaration);
    } else if (declaration instanceof EnumTypeDeclaration) {
      return _generateSerializationStatementForUserTypeArray(body, type, elementType, (EnumTypeDeclaration)declaration);
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.<Object>asList(body, type, elementType, declaration).toString());
    }
  }
  
  public CharSequence generateSerializationStatementForGenericListType(final BodyBlock body, final GenericListType type, final Type elementType) {
    if (elementType instanceof IntrinsicType) {
      return _generateSerializationStatementForGenericListType(body, type, (IntrinsicType)elementType);
    } else if (elementType instanceof UserType) {
      return _generateSerializationStatementForGenericListType(body, type, (UserType)elementType);
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.<Object>asList(body, type, elementType).toString());
    }
  }
  
  public CharSequence generateSerializationStatementForUserTypeGenericList(final BodyBlock body, final GenericListType type, final UserType elementType, final UserTypeDeclaration declaration) {
    if (declaration instanceof ComplexTypeDeclaration) {
      return _generateSerializationStatementForUserTypeGenericList(body, type, elementType, (ComplexTypeDeclaration)declaration);
    } else if (declaration instanceof EnumTypeDeclaration) {
      return _generateSerializationStatementForUserTypeGenericList(body, type, elementType, (EnumTypeDeclaration)declaration);
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.<Object>asList(body, type, elementType, declaration).toString());
    }
  }
}
